package com.flyqiu.common.property;

import com.flyqiu.common.clazz.FlyQiuClassTools;
import com.flyqiu.common.clazz.FlyQiuFieldFilter;
import com.flyqiu.common.std.FlyQiuBooleanFun;
import com.flyqiu.common.tools.FlyQiuCollectionTools;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.function.Function;

/**
 * 提供获取类属性的工具类。
 */
public class FlyQiuPropertyTools {

    /**
     * 过滤器：排除静态和最终字段。
     */
    private static final FlyQiuFieldFilter IS_OBJECT_VAR = (field, clazz) -> {
        if (Modifier.isFinal(field.getModifiers())) {
            return false;
        }
        return !Modifier.isStatic(field.getModifiers());
    };

    /**
     * 获取类的所有非静态非最终字段属性。
     *
     * @param clazz 类对象
     * @param <T>   类的泛型类型
     * @return 字段属性列表
     */
    public static <T> List<FlyQiuFieldProperty> getProperties(Class<T> clazz) {
        return FlyQiuClassTools.getAllFields(clazz, IS_OBJECT_VAR, FlyQiuFieldProperty::new);
    }

    /**
     * 获取类的所有非静态非最终字段属性，并将其映射为字段名称到属性的映射表。
     *
     * @param clazz 类对象
     * @param <T>   类的泛型类型
     * @return 字段名称到属性的映射表
     */
    public static <T> Map<String, FlyQiuFieldProperty> getPropertyMap(Class<T> clazz) {
        return FlyQiuClassTools.getAllFieldMap(clazz, IS_OBJECT_VAR, FlyQiuFieldProperty::new);
    }

    /**
     * 获取类的所有非静态非最终字段属性，并应用额外的过滤器。
     *
     * @param clazz  类对象
     * @param filter 额外的过滤器
     * @param <T>    类的泛型类型
     * @return 字段属性列表
     */
    public static <T> List<FlyQiuFieldProperty> getProperties(Class<T> clazz, FlyQiuFieldFilter filter) {
        FlyQiuFieldFilter fieldFilter = IS_OBJECT_VAR;
        if (filter != IS_OBJECT_VAR) {
            fieldFilter = IS_OBJECT_VAR.andThen(filter);
        }
        return FlyQiuClassTools.getAllFields(clazz, fieldFilter, FlyQiuFieldProperty::new);
    }

    /**
     * 获取类的所有非静态非最终字段属性，并将其映射为字段名称到属性的映射表，并应用额外的过滤器。
     *
     * @param clazz  类对象
     * @param filter 额外的过滤器
     * @param <T>    类的泛型类型
     * @return 字段名称到属性的映射表
     */
    public static <T> Map<String, FlyQiuFieldProperty> getPropertyMap(Class<T> clazz, FlyQiuFieldFilter filter) {
        FlyQiuFieldFilter fieldFilter = IS_OBJECT_VAR;
        if (filter != IS_OBJECT_VAR) {
            fieldFilter = IS_OBJECT_VAR.andThen(filter);
        }
        return FlyQiuClassTools.getAllFieldMap(clazz, fieldFilter, FlyQiuFieldProperty::new);
    }



    /**
     * 获取类的所有非静态非最终字段属性，并应用额外的过滤器及值映射函数。
     *
     * @param clazz     类对象
     * @param filter    额外的过滤器
     * @param valMapper 值映射函数
     * @param <T>       类的泛型类型
     * @param <V>       映射结果的泛型类型
     * @return 映射结果列表
     */
    public static <T, V> List<V> getProperties(Class<T> clazz, FlyQiuFieldFilter filter, Function<Field, V> valMapper) {
        return FlyQiuClassTools.getAllFields(clazz, IS_OBJECT_VAR.andThen(filter), valMapper);
    }

    /**
     * 根据给定的Map对象获取其所有属性，不带任何过滤条件
     *
     * @param map 包含属性的Map对象
     * @return 属性的列表
     */
    public static List<FlyQiuBaseProperty> getProperties(Map<?, ?> map) {
        return getProperties(map, fiyQiuMapProperty -> true);
    }

    /**
     * 根据给定的Map对象获取其属性，并通过过滤函数进行筛选
     *
     * @param map    包含属性的Map对象
     * @param filter 过滤函数，用于筛选属性
     * @return 筛选后的属性列表
     */
    public static List<FlyQiuBaseProperty> getProperties(Map<?, ?> map, FlyQiuBooleanFun<FlyQiuBaseProperty> filter) {
        List<FlyQiuBaseProperty> result = new ArrayList<>();
        if (FlyQiuCollectionTools.isEmpty(map)) {
            return result;
        }
        Set<?> set = map.keySet();
        FiyQiuMapProperty property;
        for (Object obj : set) {
            property = new FiyQiuMapProperty(obj);
            if (!filter.apply(property)) {
                continue;
            }
            result.add(property);
        }
        return result;
    }

    /**
     * 根据给定的Map对象获取其所有属性，并不带任何过滤条件，返回Map形式
     *
     * @param map 包含属性的Map对象
     * @return 属性的Map集合
     */
    public static Map<Object, FlyQiuBaseProperty> getPropertyMap(Map<?, ?> map) {
        return getPropertyMap(map, fiyQiuMapProperty -> true);
    }

    /**
     * 根据给定的Map对象获取其属性，并通过过滤函数进行筛选，返回Map形式
     *
     * @param map    包含属性的Map对象
     * @param filter 过滤函数，用于筛选属性
     * @return 筛选后的属性Map集合
     */
    public static Map<Object, FlyQiuBaseProperty> getPropertyMap(Map<?, ?> map, FlyQiuBooleanFun<FlyQiuBaseProperty> filter) {
        Map<Object, FlyQiuBaseProperty> result = new LinkedHashMap<>();
        if (FlyQiuCollectionTools.isEmpty(map)) {
            return result;
        }
        Set<?> set = map.keySet();
        FiyQiuMapProperty property;
        for (Object obj : set) {
            property = new FiyQiuMapProperty(obj);
            if (!filter.apply(property)) {
                continue;
            }
            result.put(property.getName(), property);
        }
        return result;
    }
}
